package pl.lodz.p.browarex.mvc;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;

import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestWrapper;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import pl.lodz.p.browarex.model.AnalysiesListType;
import pl.lodz.p.browarex.model.AnalysisType;
import pl.lodz.p.browarex.model.Customer;
import pl.lodz.p.browarex.model.Order;
import pl.lodz.p.browarex.model.OrderProductInfo;
import pl.lodz.p.browarex.model.Product;
import pl.lodz.p.browarex.model.enums.AnalysisTypeEnum;
import pl.lodz.p.browarex.model.enums.OrderState;
import pl.lodz.p.browarex.model.enums.Role;
import pl.lodz.p.browarex.services.interfaces.IAnalysisTypeService;
import pl.lodz.p.browarex.services.interfaces.ICustomerService;
import pl.lodz.p.browarex.services.interfaces.IOrderProductInfoService;
import pl.lodz.p.browarex.services.interfaces.IOrderService;
import pl.lodz.p.browarex.services.interfaces.IProductService;
import pl.lodz.p.browarex.services.interfaces.IUserService;
import pl.lodz.p.browarex.utils.Utils;
import pl.lodz.p.browarex.validator.OrderInfoValidator;

@Controller
public class IndexController {

	@Inject
	IProductService productService;
	@Inject
	IOrderProductInfoService orderProductInfoService;
	@Inject
	IOrderService orderService;
	@Inject
	IUserService userService;
	@Inject
	ICustomerService customerService;
	@Inject
	IAnalysisTypeService analysisTypeService;
	@Autowired
	OrderInfoValidator orderValidator;

	@InitBinder
	public void initBinder(WebDataBinder dataBinder) {
		dataBinder.setValidator(orderValidator);
	}

	@RequestMapping("index")
	public String showLoginPage(Model model, HttpServletRequest request)
			throws Exception {

		model.addAttribute("orderProductInfo", new OrderProductInfo());
		model.addAttribute("productsList", productService.list());

		Object principal = SecurityContextHolder.getContext()
				.getAuthentication().getPrincipal();
		boolean isAnonymous = true;
		if (principal instanceof UserDetails) {
			String username = ((UserDetails) principal).getUsername();
			SecurityContextHolderAwareRequestWrapper scharw = new SecurityContextHolderAwareRequestWrapper(
					request, username);
			isAnonymous = false;
			if (request.isUserInRole(Role.CUSTOMER.toString())) {
				System.out.println("Customerek");

			}
			System.out.println("Zalogowany jako: " + username);
		} else {
			String username = principal.toString();
			System.out.println("Zalogowany jako: " + username);
		}
		if (!isAnonymous) {
			AnalysisType analysisList = analysisTypeService
					.loadByCustomerID(customerService.getByUsername(
							userService.getLogged().getUsername())
							.getCustomerID());
			if (analysisList != null) {
				for (int i = 0; i < analysisList.getAnalysies().size(); i++) {
					if (AnalysisTypeEnum.FAVORITE_BRAND.equals(analysisList
							.getAnalysies().get(i).getType())
							&& analysisList.getAnalysies().get(i)
									.getProductID() != null) {
						String brandURL = "<a href = \"manufacturer?name="
								+ analysisList.getAnalysies().get(i)
										.getProduct().getManufacturer()
								+ "\">tutaj" + "</a>";
						model.addAttribute("link", brandURL);
					}
				}
			}
		}

		return "index";
	}

	private List<Product> sortWithAnalysis(List<Product> list) {
		AnalysisType analysisList;
		try {
			analysisList = analysisTypeService.loadByCustomerID(customerService
					.getByUsername(userService.getLogged().getUsername())
					.getCustomerID());
		} catch (NullPointerException e) {
			return productService.list();
		}
		List<Product> toDelete = list;
		List<Product> newItems = new ArrayList<Product>();
		for (AnalysiesListType listItem : analysisList.getAnalysies()) {
			if (listItem.getType().equals(AnalysisTypeEnum.FAVORITE_BRAND)) {
				for (int i = 0; i < toDelete.size(); i++) {
					if (toDelete.get(i).getProductID()
							.equals(listItem.getProductID())) {
						newItems.add(toDelete.get(i));
						toDelete.remove(i);
					}
				}
			}
		}
		for (AnalysiesListType listItem : analysisList.getAnalysies()) {
			if (listItem.getType().equals(AnalysisTypeEnum.PRICE_MATCH)) {
				for (int i = 0; i < toDelete.size(); i++) {
					if (toDelete.get(i).getProductID()
							.equals(listItem.getProductID())) {
						newItems.add(toDelete.get(i));
						toDelete.remove(i);
					}
				}
			}
		}
		for (Product prod : toDelete) {
			newItems.add(prod);
		}
		return newItems;
	}

	@RequestMapping(value = "/addToBasket", method = RequestMethod.POST)
	public String addContact(OrderProductInfo orderProductInfo,
			BindingResult result, Model model) {
		orderProductInfo.setProduct(productService.load(orderProductInfo
				.getProduct().getId()));
		orderProductInfo.setProductCode(orderProductInfo.getProduct()
				.getProductID());
		orderProductInfo.setProductName(orderProductInfo.getProduct()
				.getProductName());
		orderValidator.validate(orderProductInfo, result);
		if (result.hasErrors()) {

			model.addAttribute("orderProductInfo", orderProductInfo);
			model.addAttribute("productsList", productService.list());

			return "index";
		}
		Customer loggedCustomer = customerService.load(userService.getLogged()
				.getId());

		double discount = Utils
				.getDiscount(loggedCustomer, analysisTypeService);
		orderProductInfo.setPrice(orderProductInfo.getProduct().getPrice()
				* orderProductInfo.getQuantity() * (1.0 - discount));

		Order order = orderService.getBasketOrderForCustomer(loggedCustomer);
		if (order == null) {
			order = new Order();
			order.setOrderDate(new Date());
			order.setOrderID(UUID.randomUUID().toString());
			order.setCustomer(loggedCustomer);
			order.setOrderState(OrderState.BASKET);
			orderService.save(order);
		}
		orderService.addToOrder(order, orderProductInfo, discount);

		model.addAttribute("productsList", productService.list());
		model.addAttribute("orderProductInfo", new OrderProductInfo());
		return "index";
	}

}
